package com.ash.nio.tcp.chat;


import com.ash.nio.BuffUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class ChatServer {


    public static void main(String[] args) throws IOException {

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8081));
        serverSocketChannel.configureBlocking(false);


        Selector selector = Selector.open();

        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            System.out.println("等待事件发生阻塞。。。");
            int select = selector.select();
            System.out.println("来活了，干活。。。");
            if (select <= 0) {
                System.out.println("没有事件");
                continue;
            }

            // 获取事件列表
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();

            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();

                if (selectionKey.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);

                    socketChannel.register(selector, SelectionKey.OP_READ);
                }


                if (selectionKey.isReadable()) {
                    ByteBuffer attachment = ByteBuffer.allocate(1024);
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

                    try {
                        int read = socketChannel.read(attachment);
                        if (read == -1) {
                            closeAndDeregisterChannel(selectionKey, socketChannel);
                            return;
                        }

                        String requestBody = BuffUtil.byteBuffString(attachment);
                        System.out.println(requestBody);

                        // 发送给所有用户,包括请求者自己
                        Set<SelectionKey> keys = selector.keys();
                        attachment.flip();
                        for (SelectionKey key : keys) {
                            SelectableChannel channel = key.channel();
                            if (channel instanceof SocketChannel) {
                                sendMsgToAll(requestBody, key);
                            }
                        }

                        attachment.clear();

                    } catch (IOException e) {
                        closeAndDeregisterChannel(selectionKey, socketChannel);
                    }
                }

                iterator.remove();
            }


        }


    }

    private static void sendMsgToAll(String attachment, SelectionKey key) {
        SocketChannel channel = null;
        try {
            channel = (SocketChannel) key.channel();
            System.out.println("消息发送给" + channel.getRemoteAddress());

            channel.write(ByteBuffer.wrap(attachment.getBytes(StandardCharsets.UTF_8)));
        } catch (IOException e) {
            closeAndDeregisterChannel(key, channel);
        }
    }


    // 定义一个方法用于关闭通道并从选择器中取消注册
    private static void closeAndDeregisterChannel(SelectionKey selectionKey, SelectableChannel channel) {
        try {
            System.out.println("关闭连接");
            selectionKey.cancel();
            if (channel instanceof SocketChannel) {
                ((SocketChannel) channel).close();
            }
        } catch (IOException e) {
            System.err.println("关闭通道时发生异常: " + e.getMessage());
        }
    }


}
